package com.login.sotokensso3client.controller;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.sso.message.SaSsoMessage;
import cn.dev33.satoken.sso.processor.SaSsoClientProcessor;
import cn.dev33.satoken.sso.template.SaSsoClientTemplate;
import cn.dev33.satoken.sso.template.SaSsoClientUtil;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import com.alibaba.fastjson.JSONObject;
import com.login.sotokensso3client.entity.SysUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * Sa-Token-SSO Client端 Controller 
 * @author click33
 */
@Slf4j
@RestController
public class SsoClientController {

	// SSO-Client端：首页
	@RequestMapping("/")
	public String index() {
		String str = "<h2>Sa-Token SSO-Client 应用端 (模式三)</h2>" +
				"<p>当前会话是否登录：" + StpUtil.isLogin() + " (" + StpUtil.getLoginId("") + ")</p>" +
				"<p> " +
					"<a href='/sso/login?back=/'>登录</a> - " +
					"<a href='/sso/logoutByAlone?back=/'>单应用注销</a> - " +
					"<a href='/sso/logout?back=self&singleDeviceIdLogout=true'>单浏览器注销</a> - " +
					"<a href='/sso/logout?back=self'>全端注销</a> - " +
					"<a href='/sso/myInfo' target='_blank'>账号资料</a>" +
				"</p>";
		return str;
	}
	
	/*
	 * SSO-Client端：处理所有SSO相关请求
	 * 		http://{host}:{port}/sso/login			-- Client 端登录地址
	 * 		http://{host}:{port}/sso/logout			-- Client 端注销地址（isSlo=true时打开）
	 * 		http://{host}:{port}/sso/pushC			-- Client 端接收消息推送地址
	 */
	@RequestMapping("/sso/*")
	public Object ssoRequest() {
		return SaSsoClientProcessor.instance.dister();
	}

	// 配置SSO相关参数 
	@Autowired
	private void configSso(SaSsoClientTemplate ssoClientTemplate) {
		// 自定义校验 ticket 返回值的处理逻辑 （每次从认证中心获取校验 ticket 的结果后调用）
		ssoClientTemplate.strategy.ticketResultHandle = (ctr, back) -> {
			log.info("--------- 自定义 ticket 校验结果处理函数 ---------");
			log.info("此账号在 sso-server 的 userId：" + ctr.loginId);
			log.info("此账号在 sso-server 会话剩余有效期：" + ctr.remainSessionTimeout + " 秒");
			log.info("此账号返回的 user 信息：" + ctr.result.get("user"));
			// 模拟代码：
			// 根据 email 字段找到此账号在本系统对应的 user 信息
			SysUser user = JSONObject.parseObject(ctr.result.get("user").toString(), SysUser.class);
			String phone = user.getPhone();
			//根据手机号码查询用户
			SysUser userInfo=user;
			// 如果找不到，说明是首次登录本系统的新用户，需要自动注册一个新账号给他
			if(userInfo == null) {
				// 涉及到数据库操作，此处仅做模拟代码
				// 1、构建 user 信息
				// 2、插入到数据库
				// 3、查询出最新刚插入的这条 user 信息
//				user = sysUserMapper.getByPhome(phone);
			}

			// 进行登录
			StpUtil.login(user.getId(), ctr.remainSessionTimeout);
			StpUtil.getSession().set("user", ctr.result.get("user"));

			// 一切工作完毕，重定向回 back 页面
			return SaHolder.getResponse().redirect(back);
		};

	}

	// 当前应用独自注销 (不退出其它应用)
	@RequestMapping("/sso/logoutByAlone")
	public Object logoutByAlone() {
		StpUtil.logout();
		return SaSsoClientProcessor.instance._ssoLogoutBack(SaHolder.getRequest(), SaHolder.getResponse());
	}

	// 查询我的账号信息：sso-client 前端 -> sso-center 后端 -> sso-server 后端
	@RequestMapping("/sso/myInfo")
	public Object myInfo() {
		// 如果尚未登录
		if( ! StpUtil.isLogin()) {
			return "尚未登录，无法获取";
		}

		// 获取本地 loginId
		Object loginId = StpUtil.getLoginId();

		// 推送消息
		SaSsoMessage message = new SaSsoMessage();
		message.setType("userinfo");
		message.set("loginId", loginId);
		SaResult result = SaSsoClientUtil.pushMessageAsSaResult(message);

		// 返回给前端
		return result;
	}

}
